# -*- coding=utf-8 -*-
# Author: Linpeng Sun
# @Date : 2021-07-02
import os

import xlrd


class ReadData:

    def __init__(self, project=None):
        '''

        :param project: 根据参数获得项目名称去读取excle中的sheet页， 默认为None
        '''
        sep = os.sep  # os.sep根据你所处的平台，自动采用相应的分隔符号(Windows分隔符是'\'，在Linux上是'/')
        try:
            # 获得项目根目录
            root_path = os.path.abspath(os.path.join(__file__, f"..{sep}..{sep}.."))
            # xlsx表格数据地址
            form_path = f"{root_path}{sep}data{sep}api_cases.xlsx"
            # 读取xlsx表格数据
            self.workbook = xlrd.open_workbook(form_path)  # 整个xlxs数据对象
            self.sheetNames = self.workbook.sheet_names()  # 页签名称列表
            # 生成一个页签名称对应页签对象的字典
            self.form_data = {}
            for sheet in self.sheetNames:
                self.form_data[sheet] = self.workbook.sheet_by_name(sheet)

            # 判断传入的项目名称是否有效
            if project and self.sheetNames.__contains__(project):
                self.pro = project
                print(self.pro)
            else:
                print("\033[1;31m请确认【%s】名称是否正确或在表格中补充【%s】项目信息！！！\033[0m" % (project, project))

        except Exception as e:
            print(e)

    # 根据传入的项目名称获取表格中页签对象
    def get_sheetData(self) -> xlrd.sheet.Sheet:
        sheet_data = self.form_data[self.pro]
        print(sheet_data)
        return sheet_data

    # 根据表格数据获取列数据名称
    def get_titleData(self) -> list:
        head_list = self.get_sheetData().row_values(0)
        print(head_list)
        return head_list

    # 返回表格数据列表表头总列数
    def row_Nums(self) -> int:
        num_rows = len(self.get_titleData())
        print(num_rows)
        return num_rows

    # 根据传入表头名称返回对应的当前列数
    def get_num_name(self, title_name) -> int:
        """
        :param title_name:          excle表头中的字段名称
        :return:                    excle表头中该字段所在列数
        """
        for name in self.get_titleData():
            if title_name == name:
                print(self.get_titleData().index(title_name))
                return self.get_titleData().index(title_name)

    # 根据传入的表头名称参数返回一个字典对象：key-表头名称， value-列数
    def get_dict_name(self, title_name_list) -> dict:
        title_name_dict = {}
        for name in title_name_list:
            try:
                title_name_dict[name] = self.get_titleData().index(name)
            except Exception as er:
                print("\033[1;31m %s\033[0m" % str(er))
        print(title_name_dict)
        return title_name_dict

    # 判断填写的表格数据是否符合规范
    def table_is_norm(self) -> bool:
        norm_list = ["环境", "模块名", "接口名称", "请求方法", "请求头", "请求参数", "用例描述", "请求体", "预期结果"]
        head_list = self.get_titleData()
        for title in norm_list:
            if not head_list.__contains__(title):
                print("\033[1;31m列表数据中缺乏 %s, 请在列表中补全相关数据！\033[0m" % title)
                return False
            else:
                pass
        return True

    # 根据传入的模块名称获取模块测试数据
    def get_module_data(self, fieldName=None) -> list:
        """
        :param fieldName:          根据传入的模块名称筛选该模块的测试数据
        :return:                   返回该模块筛选出来的测试数据
        """
        sheet_data = self.get_sheetData()
        fieldName_num = self.get_num_name("模块名")
        headers_num = self.get_num_name("请求头")
        body_num = self.get_num_name("请求体")
        para_num = self.get_num_name("请求参数")
        expect_num = self.get_num_name("预期结果")
        Table_data = []
        # 根据模块名fieldName把表格中的数据放在一起，后面如果有需要可以进行ddt
        for num in range(1, sheet_data.nrows):
            if sheet_data.row_values(num)[fieldName_num] == fieldName:
                row_data = []
                # 把每行数据中的 headers/body/断言结果 单独取出来
                special_data_list = [sheet_data.row_values(num)[headers_num], sheet_data.row_values(num)[body_num],
                                     sheet_data.row_values(num)[expect_num], sheet_data.row_values(num)[para_num]]
                for cell in sheet_data.row_values(num):
                    if cell in special_data_list and cell:
                        # 将 header/body/预期结果中的 json格式的特殊数据类型转换为Python支持的数据类型
                        cell = cell.replace('null', 'None')
                        cell = cell.replace('false', 'False')
                        cell = cell.replace('true', 'True')
                        cell = cell.replace(' ', ' ')
                    try:
                        cell = eval(cell)  # 这里做eval转换的目的是避免后期做，不然生成的报告中测试方法名称是一长串字符
                    except Exception:
                        pass
                    row_data.append(cell)
                Table_data.append(row_data)
        print(Table_data)
        return Table_data

    # 根据传入的模块名称和接口名称过滤出需要的ddt测试数据
    def get_data_by_api(self, fieldName=None, api_name=None) -> list:
        """
        :param fieldName:         模块名称，默认为None
        :param api_name:          接口名称，默认为None
        :return:                  根据模块名称和接口名称进行二次筛选，返回用于单个接口进行ddt的测试数据
        """
        env = 'prod'
        test_data_list = []
        # 根据传入的模块名称获取模块测试数据
        data = self.get_module_data(fieldName=fieldName)
        api_name_num = self.get_num_name("接口名称")
        api_env_num = self.get_num_name("环境")
        for i in range(len(data)):
            if data[i][api_name_num] == api_name and data[i][api_env_num] == env:
                test_data_list.append(data[i])
        print(test_data_list)
        return test_data_list


if __name__ == '__main__':
    obj = ReadData('ddmf')
    # obj.get_sheetData()
    # obj.get_titleData()
    # obj.row_Nums()
    # obj.get_num_name('模块名')
    # obj.get_dict_name(['模块名','接口名称'])
    # obj.get_module_data("Login")
    obj.get_data_by_api('XF','XF_Newshot')
